package com.example.jedis.client.command;


import com.example.jedis.client.command.key.RedisKeyCommandImpl;
import com.example.jedis.client.command.string.RedisStringCommandImpl;
import com.example.jedis.client.protocol.request.RequestProtocolImpl;
import com.example.jedis.client.protocol.response.*;
import com.example.jedis.client.transport.RedisTransport;
import com.example.jedis.client.transport.RedisTransportForLog;
import com.example.jedis.client.transport.RedisTransportImpl;
import redis.clients.jedis.exceptions.JedisException;

import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

public class RedisCommandsSimpleBuilder {
    String host;
    int port;

    public RedisCommandsSimpleBuilder host(String host){
        this.host = host;
        return this;
    }
    public RedisCommandsSimpleBuilder port(int port){
        this.port =port;
        return this;
    }
    public RedisCommands build()  {
        try {
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(true);
            socketChannel.setOption(StandardSocketOptions.SO_LINGER, -1);
            socketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 128 * 1024);
            socketChannel.setOption(StandardSocketOptions.SO_SNDBUF, 128 * 1024);
            socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
            socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
            boolean connected = socketChannel.connect(new InetSocketAddress(this.host, this.port));
            if (!connected) {
                throw new RuntimeException("connect fail to " + this.host + ":" + this.port);
            } else {
                RedisTransport redisTransportImpl = new RedisTransportImpl(socketChannel);
                RedisTransportForLog redisTransportForLog = new RedisTransportForLog(redisTransportImpl);
                RedisTransport redisTransport = redisTransportForLog;
                RequestProtocolImpl requestProtocol = new RequestProtocolImpl();
                requestProtocol.setRedisTransport(redisTransport);
                List<ApplyProtocol> applyProtocolList = new ArrayList<>();
                applyProtocolList.add(new ApplyStatus());
                applyProtocolList.add(new ApplyError());
                applyProtocolList.add(new ApplyBulk());
                applyProtocolList.add(new ApplyInteger());
                ResponseProtocolImpl responseProtocol = new ResponseProtocolImpl();
                responseProtocol.setRedisTransport(redisTransport);
                responseProtocol.setApplyProtocolList(applyProtocolList);

                RedisKeyCommandImpl redisKeyCommand = new RedisKeyCommandImpl();
                redisKeyCommand.setRequestProtocol(requestProtocol);
                redisKeyCommand.setResponseProtocol(responseProtocol);

                RedisStringCommandImpl redisStringCommand = new RedisStringCommandImpl();
                redisStringCommand.setRequestProtocol(requestProtocol);
                redisStringCommand.setResponseProtocol(responseProtocol);

                RedisCommands redisCommands = new RedisCommands();
                redisCommands.setRedisKeyCommand(redisKeyCommand);
                redisCommands.setRedisStringCommand(redisStringCommand);
                return redisCommands;
            }
        }catch (Exception e){
            throw new JedisException(e);
        }
    }
}
